package com.stx.handler;

import com.sun.istack.internal.Nullable;

import java.util.HashMap;
import java.util.Map;

public class Looper {

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    static final Map<Long, Looper> sThreadMap = new HashMap<Long, Looper>();

    private static Looper sMainLooper;  // guarded by Looper.class
    public final MessageQueue mQueue;
    private final Thread mThread;


    /**
     * 创建一个looper
     */
    public static void prepare(){
        prepare(true);
    }

    public static void prepare(boolean quitAllowed){
        if (sThreadLocal.get() != null){
            throw new RuntimeException("one thread only one looper");
        }
        Looper looper = new Looper(quitAllowed);
        sThreadLocal.set(looper);
        long id = Thread.currentThread().getId();
        sThreadMap.put(id, looper);
    }

    public static @Nullable
    Looper myLooper() {
       return sThreadLocal.get();
    }

    public static MessageQueue myQueue(){
        return myLooper().mQueue;
    }

    /**
     * 根据线程ID获取looper
     * @param t
     * @return
     */
    public static Looper getLooper(Thread t){
        long id = t.getId();
        if (sThreadMap.containsKey(id)){
            return sThreadMap.get(id);
        }
        return null;
    }


    /**
     * 判断是否是同一个线程
     * @return
     */
    public boolean isCurrentThread(){
        return Thread.currentThread() == mThread;
    }

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

    public static void loop(){
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        for (;;){
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                System.out.println("exit loop...");
                return;
            }
            try{
                msg.target.dispatchMessage(msg);
            }catch(Exception e){
                e.printStackTrace();
            }
            msg.recycleUnchecked();
        }
    }

    public void quit(){
        mQueue.quit(false);
    }

    public void quitSafely(){
        mQueue.quit(true);
    }

    public Thread getThread(){
        return mThread;
    }

    public MessageQueue getQueue(){
        return mQueue;
    }

    private Looper(boolean quitAllowed){
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

}





